package com.wx.gof.pattern.creational.singleton;

/**
 * @ClassName Application
 * @Author wx
 * @Description 单例模式-懒汉(synchronized锁,减少锁的粒度，提高性能)
 * @Date 2018-12-05
 */
public class LazyDoubleCheckSingleton {
    private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null;

    private LazyDoubleCheckSingleton() {
        if (lazyDoubleCheckSingleton != null){
            throw new RuntimeException("单例构造器禁止反射调用");
        }
    }

    /**
     * 此方法带会有指令重排的问题，在单线程jvm创建对象的过程的中，jvm会通过重排做优化，有可能会先置lazyDoubleCheckSingleton 指向刚分配的内存地址
     * 再初始化对象，这个时候其他线程可能会进来获取到没有创建完的对象拿出去使用，导致程序报错，解决指令重排有两种方法
     * 1.volatile内存可见性，每次主存数据更新了，其他线程的对应的缓存作废，重新去主存获取
     * 2.静态内部类，利用class对象锁机制
     */
    public static LazyDoubleCheckSingleton getInstance() {
        if (lazyDoubleCheckSingleton == null) {
            synchronized (LazyDoubleCheckSingleton.class) {
                if (lazyDoubleCheckSingleton == null) {
                    lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
                    //1.分配内存给这个对象
//                  //3.设置lazyDoubleCheckSingleton 指向刚分配的内存地址
                    //2.初始化对象
//                    intra-thread semantics
//                    ---------------//3.设置lazyDoubleCheckSingleton 指向刚分配的内存地址
                }

            }
        }
        return lazyDoubleCheckSingleton;
    }
}
